package com.luoruihang.logstatementgenerator.domain.service;

import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.luoruihang.logstatementgenerator.application.IGenerateLogStatement;
import com.luoruihang.logstatementgenerator.domain.model.ActionContext;
import com.luoruihang.logstatementgenerator.domain.model.LlmRequest;
import com.luoruihang.logstatementgenerator.domain.model.LlmResponse;
import com.luoruihang.logstatementgenerator.domain.model.LlmResult;

public abstract class AbstractGenerateLogStatement implements IGenerateLogStatement {
	@Override
	public void doGenerate(DataContext context) {
		// 0. 包装上下文环境
		ActionContext actionContext=
			constructActionContext(context.getData(CommonDataKeys.PROJECT), context, context.getData(CommonDataKeys.EDITOR));
		// 1. 获取选中的代码字段和其他需要的数据，包装成请求参数
		LlmRequest llmRequestParams = getLlmRequestParams(actionContext);
		// 2. 参数加入到请求中，发送post异步或请求
		LlmResponse llmResponse = getLlmResponse(llmRequestParams, actionContext);
		// 3. 根据上述响应，获取最终结果然后处理
		LlmResult llmResult = getLlmResult(llmResponse, actionContext);
		// 4. 根据获取的结果在指定位置生成推荐代码
		generateLogStatement(llmResult, actionContext);
	}

	protected abstract ActionContext constructActionContext(Project project, DataContext context, Editor editor);

	/**
	 * 将选中的文本及其他需要的信息包装成请求参数
	 * @param context
	 * @return
	 */
	protected abstract LlmRequest getLlmRequestParams(ActionContext context);

	/**
	 * 向外部请求，同步或异步请求，决定了最后得到最终结果的方式
	 * @param llmRequestParams
	 * @return
	 */
	protected abstract LlmResponse getLlmResponse(LlmRequest llmRequestParams, ActionContext context);

	/**
	 * 若为同步请求，直接从response结果中得到相应代码
	 * 若为异步请求，则从response中得到id任务单，轮询请求在最终结果
	 * 最后包装成LlmResult，包括生成的日志语句主体，位置等
	 * @param llmResponse
	 * @return
	 */
	protected abstract LlmResult getLlmResult(LlmResponse llmResponse, ActionContext context);

	/**
	 * 根据得到的结果，在指定位置生成指定的日志语句，有必要时生成导包语句
	 * @param llmResult
	 */
	protected abstract void generateLogStatement(LlmResult llmResult, ActionContext context);
}
